﻿using System;
using System.Diagnostics;
using System.Reflection;

namespace System.Runtime.CompilerServices
{
#if NET4_0
    /// <summary>
    /// 调用者信息特征辅助类
    /// </summary>
    public class CallerHelper
    {
        /// <summary>
        /// 获取调用者特征
        /// </summary>
        /// <param name="filePath">调用者文件路径</param>
        /// <param name="lineNum">调用者文件中的行号</param>
        /// <param name="memberName">调用者文件中函数名</param>
        public static void GetCallerFeature(out string filePath, out int lineNum, out string memberName)
        {
            var stackTrace = new StackTrace(3, true);
            StackFrame stackFrame = stackTrace.GetFrame(0);
            if (stackFrame == null)
            {
                filePath = null;
                lineNum = -1;
                memberName = null;
                return;
            }

            filePath = stackFrame.GetFileName();
            lineNum = stackFrame.GetFileLineNumber();
            //int colNo = sf.GetFileColumnNumber();

            MethodBase methodBase = stackFrame.GetMethod();
            memberName = methodBase.Name;
        }
    }

    /// <summary>
    /// 调用文件特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class CallerFilePathAttribute : Attribute
    {
        /// <summary>
        /// 
        /// </summary>
        public CallerFilePathAttribute()
        {

        }
    }

    /// <summary>
    /// 调用行号特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class CallerLineNumberAttribute : Attribute
    {
        /// <summary>
        /// 
        /// </summary>
        public CallerLineNumberAttribute()
        {

        }
    }

    /// <summary>
    /// 调用方法名特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public sealed class CallerMemberNameAttribute : Attribute
    {
        /// <summary>
        /// 
        /// </summary>
        public CallerMemberNameAttribute()
        {

        }

        /// <summary>
        /// 获取调用方的方法或属性名称
        /// </summary>
        /// <returns>调用方的方法或属性名称</returns>
        public static string GetName()
        {
            var st = new System.Diagnostics.StackTrace(2, true);
            System.Diagnostics.StackFrame sf = st.GetFrame(0);
            System.Reflection.MethodBase methodBase = sf.GetMethod();
            string methodName = methodBase.Name;
            if (methodName.StartsWith("set_"))
            {
                methodName = methodName.Substring(4);
                System.Reflection.PropertyInfo propertyInfo = methodBase.ReflectedType.GetProperty(methodName);
                if (propertyInfo != null)
                {
                    return propertyInfo.Name;
                }
            }

            return methodName;
        }
    }
#endif

}
